package org.tinaelle.client.utils;

import org.tinaelle.client.gui.AdminPanel;
import org.tinaelle.client.gui.DataPanel;
import org.tinaelle.client.gui.fieldSet.AdCountryDataDetail;
import org.tinaelle.client.gui.fieldSet.AdCurrencyDataDetail;
import org.tinaelle.client.gui.fieldSet.AdElementDataDetail;
import org.tinaelle.client.gui.fieldSet.AdGroupDataDetail;
import org.tinaelle.client.gui.fieldSet.AdLanguageDataDetail;
import org.tinaelle.client.gui.fieldSet.AdMessageDataDetail;
import org.tinaelle.client.gui.fieldSet.AdParameterDataDetail;
import org.tinaelle.client.gui.fieldSet.AdScreenDataDetail;
import org.tinaelle.client.gui.fieldSet.AdSequenceDataDetail;
import org.tinaelle.client.gui.fieldSet.AdTableDataDetail;
import org.tinaelle.client.gui.fieldSet.AdTreeDataDetail;
import org.tinaelle.client.gui.fieldSet.AdUserDataDetail;
import org.tinaelle.client.gui.grid.impl.AdCountryDataProvider;
import org.tinaelle.client.gui.grid.impl.AdCurrencyDataProvider;
import org.tinaelle.client.gui.grid.impl.AdElementDataProvider;
import org.tinaelle.client.gui.grid.impl.AdGroupDataProvider;
import org.tinaelle.client.gui.grid.impl.AdLanguageDataProvider;
import org.tinaelle.client.gui.grid.impl.AdMessageDataProvider;
import org.tinaelle.client.gui.grid.impl.AdParameterDataProvider;
import org.tinaelle.client.gui.grid.impl.AdScreenDataProvider;
import org.tinaelle.client.gui.grid.impl.AdSequenceDataProvider;
import org.tinaelle.client.gui.grid.impl.AdTableDataProvider;
import org.tinaelle.client.gui.grid.impl.AdTreeDataProvider;
import org.tinaelle.client.gui.grid.impl.AdUserDataProvider;
import org.tinaelle.client.gui.tree.DataTree;
import org.tinaelle.common.dto.AdCountryDTO;
import org.tinaelle.common.dto.AdCurrencyDTO;
import org.tinaelle.common.dto.AdElementDTO;
import org.tinaelle.common.dto.AdGroupDTO;
import org.tinaelle.common.dto.AdLanguageDTO;
import org.tinaelle.common.dto.AdMessageDTO;
import org.tinaelle.common.dto.AdParameterDTO;
import org.tinaelle.common.dto.AdScreenDTO;
import org.tinaelle.common.dto.AdSequenceDTO;
import org.tinaelle.common.dto.AdTableDTO;
import org.tinaelle.common.dto.AdTreeDTO;
import org.tinaelle.common.dto.AdTreeNodeDTO;
import org.tinaelle.common.dto.AdUserDTO;
import org.tinaelle.server.service.AdTreeServiceAsync;
import org.tinaelle.server.service.AdWindowServiceAsync;

import com.google.gwt.user.client.History;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.data.ArrayReader;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.MemoryProxy;
import com.gwtext.client.data.Node;
import com.gwtext.client.data.ObjectFieldDef;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.TabPanel;
import com.gwtext.client.widgets.layout.AccordionLayout;
import com.gwtext.client.widgets.layout.FitLayout;
import com.gwtext.client.widgets.tree.TreeNode;
import com.gwtext.client.widgets.tree.TreePanel;
import com.gwtext.client.widgets.tree.event.TreeNodeListenerAdapter;

public class ScreenManager {
	private TabPanel	         appTabPanel;
	private Store	             localStore;
	private ArrayReader	         localReader;
	private MemoryProxy	         localProxy;
	private Panel	             accordion;

	private static ScreenManager	instance;

	private ScreenManager() {
	};

	public static ScreenManager getInstance() {
		if ( instance == null ) {
			instance = new ScreenManager();
		}
		return instance;
	}

	public void setTabPanel(final TabPanel tabPanel) {
		this.appTabPanel = tabPanel;
	}

	public Panel getAccordionNav() {
		accordion = new Panel();
		accordion.setTitle( "Main Menu" );
		accordion.setLayout( new AccordionLayout( true ) );
		accordion.setWidth( 200 );
		AdTreeServiceAsync.Util.getInstance().getTreeNodes( 1, new DefaultAsyncCallback<AdTreeNodeDTO[]>() {
			public void onSuccess(final AdTreeNodeDTO[] result) {
				fillAccordionNav( accordion, result );
			}
		} );
		return accordion;
	}

	public void rebuildAccordionNav() {
		accordion.removeAll( true );
		AdTreeServiceAsync.Util.getInstance().getTreeNodes( 1, new DefaultAsyncCallback<AdTreeNodeDTO[]>() {
			public void onSuccess(final AdTreeNodeDTO[] result) {
				fillAccordionNav( accordion, result );
			}
		} );
	}

	private void fillAccordionNav(final Panel accordion, final AdTreeNodeDTO[] nodes) {
		for ( int i = 0; i < nodes.length; i++ ) {
			final AdTreeNodeDTO treeNode = nodes[ i ];
			if ( !treeNode.getIsLeaf().booleanValue() ) {
				final Panel categoryPanel = new Panel();
				categoryPanel.setAutoScroll( true );
				categoryPanel.setLayout( new FitLayout() );
				categoryPanel.setId( Integer.toString( treeNode.getAdTreeNodeId() ) + "-acc" );
				categoryPanel.setTitle( treeNode.getName() );
				categoryPanel.setIconCls( treeNode.getIconCls() );

				accordion.add( categoryPanel );
				AdTreeServiceAsync.Util.getInstance().getNodes( treeNode.getAdTreeNodeId(),
				        new DefaultAsyncCallback<AdTreeNodeDTO[]>() {
					        public void onSuccess(final AdTreeNodeDTO[] result) {
						        fillAccordionNav( accordion, result );
					        }
				        } );
			} else {
				final Panel categoryPanel = ( Panel ) accordion.findByID( Integer.toString( treeNode.getParentId() )
				        + "-acc" );
				TreePanel treePanel = ( TreePanel ) categoryPanel.findByID( Integer.toString( treeNode.getParentId() )
				        + "-acc-tree" );
				TreeNode root = null;
				if ( treePanel == null ) {
					treePanel = new TreePanel();
					treePanel.setAutoScroll( true );
					treePanel.setId( Integer.toString( treeNode.getParentId() ) + "-acc-tree" );
					treePanel.setRootVisible( false );
					root = new TreeNode();
					treePanel.setRootNode( root );
					categoryPanel.add( treePanel );
				} else {
					root = treePanel.getRootNode();
				}

				final TreeNode node = new TreeNode();
				node.setText( treeNode.getName() );
				node.setId( Integer.toString( treeNode.getAdTreeNodeId() ) );
				if ( treeNode.getIconCls() != null ) {
					node.setIconCls( treeNode.getIconCls() );
				}
				if ( treeNode.getTooltip() != null ) {
					node.setTooltip( treeNode.getTooltip() );
				}
				root.appendChild( node );

				if ( treeNode.getAdScreenId() != null ) {
					AdWindowServiceAsync.Util.getInstance().getScreenById( treeNode.getAdScreenId(),
					        new DefaultAsyncCallback<AdScreenDTO>() {
						        public void onSuccess(final AdScreenDTO result) {
							        final Record screenRecord = getLocalStore().query( "id", result.getName() )[ 0 ];
							        final TinaelCenterPanel panel = ( TinaelCenterPanel ) screenRecord
							                .getAsObject( "screen" );
							        addNodeClickListener( node, panel, treeNode.getIconCls() );
						        }
					        } );
				}

			}
		}
		accordion.doLayout();
	}

	private void addNodeClickListener(final TreeNode node, final Panel panel, final String iconCls) {
		if ( panel != null ) {
			node.addListener( new TreeNodeListenerAdapter() {
				@Override
				public void onClick(final Node node, final EventObject e) {
					final String panelID = panel.getId();
					if ( appTabPanel.hasItem( panelID ) ) {
						showScreen( panel, null, null, node.getId() );
					} else {
						final TreeNode treeNode = ( TreeNode ) node;
						panel.setTitle( treeNode.getText() );
						String nodeIconCls = iconCls;
						if ( iconCls == null ) {
							nodeIconCls = ( ( TreeNode ) treeNode.getParentNode() ).getIconCls();
						}
						showScreen( panel, treeNode.getText(), nodeIconCls, node.getId() );
					}
				}
			} );
		}
	}

	public void showScreen(final String historyToken) {
		if ( ( historyToken == null ) || historyToken.equals( "" ) ) {
			appTabPanel.activate( 0 );
		} else {
			final Record record = getLocalStore().getById( historyToken );
			// Record remoteRecord = getRemoteStore().query( "adScreenId", value
			// )
			if ( record != null ) {
				final TinaelCenterPanel panel = ( TinaelCenterPanel ) record.getAsObject( "screen" );
				final String title = record.getAsString( "title" );
				final String iconCls = record.getAsString( "iconCls" );
				showScreen( panel, title, iconCls, historyToken );
			}
		}
	}

	public void showScreen(final Panel panel, final String title, String iconCls, final String screenName) {
		final String panelID = panel.getId();
		if ( appTabPanel.hasItem( panelID ) ) {
			appTabPanel.scrollToTab( panel, true );
			appTabPanel.activate( panelID );
		} else {
			if ( !panel.isRendered() ) {
				panel.setTitle( title );
				if ( iconCls == null ) {
					iconCls = "plugins-nav-icon";
				}
				panel.setIconCls( iconCls );
			}
			appTabPanel.add( panel );
			appTabPanel.activate( panel.getId() );
		}
		History.newItem( screenName );
	}

	public Store getLocalStore() {
		if ( localStore == null ) {
			localProxy = new MemoryProxy( getLocalStoreData() );

			final RecordDef recordDef = new RecordDef( new FieldDef[] {
			        new StringFieldDef( "id" ),
			        new ObjectFieldDef( "screen" ) } );

			localReader = new ArrayReader( 0, recordDef );
			localStore = new Store( localProxy, localReader );
			localStore.load();
		}
		return localStore;
	}

	public ArrayReader getLocalReader() {
		getLocalStore();
		return localReader;
	}

	public MemoryProxy getLocalProxy() {
		getLocalStore();
		return localProxy;
	}

	public Object[][] getLocalStoreData() {
		return new Object[][] {
		        {
		                "Elements",
		                new DataPanel<AdElementDTO>( new AdElementDataProvider(), AdElementDataDetail.getInstance() ) },
		        {
		                "Messages",
		                new DataPanel<AdMessageDTO>( new AdMessageDataProvider(), AdMessageDataDetail.getInstance() ) },
		        {
		                "Languages",
		                new DataPanel<AdLanguageDTO>( new AdLanguageDataProvider(), AdLanguageDataDetail.getInstance() ) },
		        {
		                "Sequences",
		                new DataPanel<AdSequenceDTO>( new AdSequenceDataProvider(), AdSequenceDataDetail.getInstance() ) },
		        { "Users", new DataPanel<AdUserDTO>( new AdUserDataProvider(), AdUserDataDetail.getInstance() ) },
		        { "Groups", new DataPanel<AdGroupDTO>( new AdGroupDataProvider(), AdGroupDataDetail.getInstance() ) },
		        {
		                "Parameters",
		                new DataPanel<AdParameterDTO>( new AdParameterDataProvider(), AdParameterDataDetail
		                        .getInstance() ) },
		        { "Screens", new DataPanel<AdScreenDTO>( new AdScreenDataProvider(), AdScreenDataDetail.getInstance() ) },
		        { "Tables", new DataPanel<AdTableDTO>( new AdTableDataProvider(), AdTableDataDetail.getInstance() ) },
		        { "Trees", new DataPanel<AdTreeDTO>( new AdTreeDataProvider(), AdTreeDataDetail.getInstance() ) },
		        { "Tree Manager", new DataTree( 1 ) },
		        {
		                "Countries",
		                new DataPanel<AdCountryDTO>( new AdCountryDataProvider(), AdCountryDataDetail.getInstance() ) },
		        {
		                "Currencies",
		                new DataPanel<AdCurrencyDTO>( new AdCurrencyDataProvider(), AdCurrencyDataDetail.getInstance() ) },
		        { "Admin", new AdminPanel() } };

	}
}
